// 使用 栈 实现浏览器的前进和后退功能
// https://blog.csdn.net/rxbook/article/details/130880001
package main

import (
	"fmt"
)

type Stack interface {
	Push(v interface{})
	Pop() interface{}
	IsEmpty() bool
	Top() interface{}
	GetTopValue() int
	Flush()
}

type Browser struct {
	forward Stack //前进的栈
	back    Stack //后退的栈
}

// 初始化
func NewBrowser() *Browser {
	return &Browser{
		forward: NewArrayStack(),
		back:    NewArrayStack(),
	}
}

// 打开一个新页面
func (this *Browser) OpenNewPage(addr string) {
	fmt.Printf("打开新页面: %v\n", addr)
	this.back.Push(addr)
	this.forward.Flush()    //清空前进的栈
	this.forward.Push(addr) //把当前最新打开的页面添加到前进的栈
}

// 从已有页面跳转到下一个页面
func (this *Browser) PushNewPage(addr string) {
	fmt.Printf("跳转到: %v\n", addr)
	this.back.Push(addr)
}

// 后退
func (this *Browser) Back() {
	if this.back.GetTopValue() == 0 {
		fmt.Println("已经后退到了第一个页面,无法再次后退")
		return
	}

	this.back.Pop()
	top := this.back.Top()
	this.forward.Push(top)
	fmt.Printf("后退到: %v\n", top)
}

// 前进
func (this *Browser) Forward() {
	if this.forward.GetTopValue() == 0 {
		fmt.Println("已经前进到了最后一个页面,无法再次前进")
		return
	}

	this.forward.Pop()
	top := this.forward.Top()
	this.back.Push(top)
	fmt.Printf("前进到: %v\n", top)
}

// go run Browser.go StackArray.go
func main() {
	browser := NewBrowser()

	// 依次访问页面 A -> B -> C
	browser.OpenNewPage("www.A.com") //打开新页面: www.A.com
	browser.PushNewPage("www.B.com") //跳转到: www.B.com
	browser.PushNewPage("www.C.com") //跳转到: www.C.com

	// 后退两次, C -> B -> A
	browser.Back() //后退到: www.B.com
	browser.Back() //后退到: www.A.com
	browser.Back() //已经后退到了第一个页面,无法再次后退
	browser.Back() //已经后退到了第一个页面,无法再次后退

	// 前进一次, A -> B
	browser.Forward() //前进到: www.B.com

	//打开一个新页面, A -> B -> D
	browser.OpenNewPage("www.D.com") //打开新页面: www.D.com

	//后退两次, D -> B -> A
	browser.Back() //后退到: www.B.com
	browser.Back() //后退到: www.A.com
	browser.Back() //已经后退到了第一个页面,无法再次后退

	//前进两次, A -> B -> D
	browser.Forward() //前进到: www.B.com
	browser.Forward() //前进到: www.D.com
	browser.Forward() //已经前进到了最后一个页面,无法再次前进
	browser.Forward() //已经前进到了最后一个页面,无法再次前进
}
